package com.wave.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wave.common.core.domain.PageQuery;
import com.wave.common.core.page.TableDataInfo;
import com.wave.common.enums.ClassesType;
import com.wave.common.utils.StringUtils;
import com.wave.system.domain.*;
import com.wave.system.domain.bo.SysProduceRecordBo;
import com.wave.system.domain.vo.SysProduceRecordStatisticsVo;
import com.wave.system.domain.vo.SysProduceRecordVo;
import com.wave.system.domain.vo.SysProduceStatisticsVo;
import com.wave.system.domain.vo.SysProductivityMonitorVo;
import com.wave.system.mapper.SysProduceRecordMapper;
import com.wave.system.mapper.SysProductConfigMapper;
import com.wave.system.mapper.SysSettingMapper;
import com.wave.system.service.ISysProduceRecordService;
import com.wave.system.util.SnCodeConvertUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 生产记录Service业务层处理
 *
 * @author wave
 * @date 2024-10-17
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class SysProduceRecordServiceImpl implements ISysProduceRecordService {

    private final SysProduceRecordMapper baseMapper;

    private final SysSettingMapper sysSettingMapper;

    private final SysProductConfigMapper sysProductConfigMapper;

    /**
     * 查询生产记录
     */
    @Override
    public SysProduceRecordVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询生产记录列表
     */
    @Override
    public TableDataInfo<SysProduceRecordVo> queryPageList(SysProduceRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysProduceRecord> lqw = buildQueryWrapper(bo);
        Page<SysProduceRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询生产记录列表
     */
    @Override
    public List<SysProduceRecordVo> queryList(SysProduceRecordBo bo) {
        LambdaQueryWrapper<SysProduceRecord> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysProduceRecord> buildQueryWrapper(SysProduceRecordBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysProduceRecord> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getShelfNumber()), SysProduceRecord::getShelfNumber, bo.getShelfNumber());
        lqw.like(StringUtils.isNotBlank(bo.getProductNumber()), SysProduceRecord::getProductNumber, bo.getProductNumber());
        lqw.gt(params.get("beginTime") != null, SysProduceRecord::getCreateTime, params.get("beginTime"));
        lqw.lt(params.get("endTime")!=null, SysProduceRecord::getCreateTime, params.get("endTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getClasses()), SysProduceRecord::getClasses, bo.getClasses());
        lqw.orderByDesc(SysProduceRecord::getCreateTime);
        return lqw;
    }

    /**
     * 新增生产记录
     */
    @Override
    public Boolean insertByBo(SysProduceRecordBo bo) {
        SysProduceRecord add = BeanUtil.toBean(bo, SysProduceRecord.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改生产记录
     */
    @Override
    public Boolean updateByBo(SysProduceRecordBo bo) {
        SysProduceRecord update = BeanUtil.toBean(bo, SysProduceRecord.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysProduceRecord entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除生产记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public SysProductivityMonitorVo getMonitorInfo(String dateStr) {
        SysProductivityMonitorVo vo = new SysProductivityMonitorVo();
        SysSetting sysSetting = sysSettingMapper.selectOne(Wrappers.lambdaQuery());
        if (ObjectUtil.isEmpty(sysSetting)) {
            return vo;
        }
        //根据白班班次时间查询白班产量
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr+ " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String[] dayShiftStartArr = sysSetting.getDayShiftStart().split(":");
        String[] dayShiftEndArr = sysSetting.getDayShiftEnd().split(":");
        LocalDateTime dayShiftStartTime = localDateTime.withHour(Integer.parseInt(dayShiftStartArr[0]))
            .withMinute(Integer.parseInt(dayShiftStartArr[1])).withSecond(0);
        LocalDateTime dayShiftEndTime = localDateTime.withHour(Integer.parseInt(dayShiftEndArr[0]))
            .withMinute(Integer.parseInt(dayShiftEndArr[1])).withSecond(0);
        List<SysProduceStatisticsVo> dayShiftList = baseMapper.selectProduceCountByClassesTime(
            Date.from(dayShiftStartTime.atZone(ZoneId.systemDefault()).toInstant()),
            Date.from(dayShiftEndTime.atZone(ZoneId.systemDefault()).toInstant()));
        //根据夜班班次时间查询夜班产量
        LocalDateTime yesterdayLocalDate = localDateTime.minusDays(1);
        String[] nightShiftStartArr = sysSetting.getNightShiftStart().split(":");
        String[] nightShiftEndArr = sysSetting.getNightShiftEnd().split(":");
        LocalDateTime nightShiftStartTime = yesterdayLocalDate.withHour(Integer.parseInt(nightShiftStartArr[0])).
            withMinute(Integer.parseInt(nightShiftStartArr[1])).withSecond(0);
        LocalDateTime nightShiftEndTime = localDateTime.withHour(Integer.parseInt(nightShiftEndArr[0]))
            .withMinute(Integer.parseInt(nightShiftEndArr[1])).withSecond(0);
        List<SysProduceStatisticsVo> nightShiftList = baseMapper.selectProduceCountByClassesTime(
            Date.from(nightShiftStartTime.atZone(ZoneId.systemDefault()).toInstant()),
            Date.from(nightShiftEndTime.atZone(ZoneId.systemDefault()).toInstant()));
        //构建返回参数
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
        String dayShiftTime = df.format(dayShiftStartTime).concat("-").concat(df.format(dayShiftEndTime));
        String nightShiftTime = df.format(nightShiftStartTime).concat("-").concat(df.format(nightShiftEndTime));
        int dayShiftTotal = dayShiftList.stream().mapToInt(SysProduceStatisticsVo::getCount).sum();
        int nightShiftTotal = nightShiftList.stream().mapToInt(SysProduceStatisticsVo::getCount).sum();
        vo.setDayShiftTime(dayShiftTime);
        vo.setDayShiftTotal(dayShiftTotal);
        vo.setDayShiftList(dayShiftList);
        vo.setNightShiftTime(nightShiftTime);
        vo.setNightShiftTotal(nightShiftTotal);
        vo.setNightShiftList(nightShiftList);
        return vo;
    }


    @Override
    public Map<String, Object> getDailyOutputTrend() {
        SysSetting sysSetting = sysSettingMapper.selectOne(Wrappers.lambdaQuery());
        if (ObjectUtil.isEmpty(sysSetting)) {
            return null;
        }
        Map<String, Object> maps = new HashMap<>();
        List<String> hours = new ArrayList<>();
        String[] dayShiftArr = sysSetting.getDayShiftStart().split(":");
        String[] nightShiftArr = sysSetting.getNightShiftEnd().split(":");
        LocalDateTime yesterdayDateTime = LocalDateTime.now().minusDays(1);
        LocalDateTime startTime = yesterdayDateTime.withHour(Integer.parseInt(dayShiftArr[0]))
            .withMinute(Integer.parseInt(dayShiftArr[1])).withSecond(0);
        LocalDateTime localDateTimeNow = LocalDateTime.now();
        LocalDateTime endTime = localDateTimeNow.withHour(Integer.parseInt(nightShiftArr[0]))
            .withMinute(Integer.parseInt(nightShiftArr[1])).withSecond(0);
        List<SysProductConfig> sysProductConfigs = sysProductConfigMapper.selectList();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm");
        while (startTime.isBefore(endTime)) {
            hours.add(df.format(startTime));
            for (SysProductConfig sysProductConfig : sysProductConfigs) {
                String productNumber = sysProductConfig.getProductNumber();
                Date start = Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant());
                LocalDateTime lastDateTime = startTime.withMinute(59).withSecond(59);
                Date end = Date.from(lastDateTime.atZone(ZoneId.systemDefault()).toInstant());
                int count = baseMapper.selectDailyOutputTrend(productNumber, start, end);
                List<Integer> list = (List<Integer>) maps.get(productNumber);
                if (ObjectUtil.isEmpty(list)) {
                    list = new ArrayList<>();
                    list.add(count);
                } else {
                    list.add(count);
                }
                maps.put(productNumber, list);
            }
            startTime = startTime.plusHours(1);
        }
        maps.put("hours", hours);
        return maps;
    }


    @Override
    public Boolean batchSaveBySnCodes(List<String> snCodes, String shelfNumber) {
        SysSetting sysSetting = sysSettingMapper.selectOne(Wrappers.lambdaQuery());
        if (ObjectUtil.isEmpty(sysSetting)) {
            log.error("保存生产记录失败，管理员未设置系统配置");
            return false;
        }
        LocalTime now = LocalTime.now();
        LocalTime start = LocalTime.parse(sysSetting.getDayShiftStart());
        LocalTime end = LocalTime.parse(sysSetting.getDayShiftEnd());
        ClassesType classesType = ClassesType.DAY_SHIFT;
        if (now.isBefore(start) && now.isAfter(end)) {
            classesType = ClassesType.NIGHT_SHIFT;
        }
        List<SysProduceRecord> list = new ArrayList<>();
        for (String snCode : snCodes) {
            SysProduceRecord record = new SysProduceRecord();
            record.setProductNumber(snCode);
            record.setProductType(SnCodeConvertUtil.getProductCodeBySnCode(snCode));
            record.setClasses(classesType.name());
            record.setCurHour(new SimpleDateFormat("HH").format(new Date()));
            record.setShelfNumber(shelfNumber);
            list.add(record);
        }
        return baseMapper.insertBatch(list);
    }

    @Override
    public Map<String, Object> getDailyOutputTrendNew(String date) {
        SysSetting sysSetting = sysSettingMapper.selectOne(Wrappers.lambdaQuery());
        if (ObjectUtil.isEmpty(sysSetting)) {
            return null;
        }

        Map<String, Object> maps = new HashMap<>();
        List<String> hours = new ArrayList<>();

        //查询昨天晚上20:00到今天晚上20:00的数据，如果当前时间为10:00，那么查询昨天晚上20:00到当前时间10:00的数据
        String[] nightShiftArr = sysSetting.getNightShiftStart().split(":");
        String[] dayShiftArr = sysSetting.getDayShiftEnd().split(":");
        LocalDateTime yesterdayDateTime = LocalDateTime.now().minusDays(1);
        if(StringUtils.isNotBlank(date) && !date.equals(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))) {
            yesterdayDateTime = LocalDateTime.parse(date + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).minusDays(1);
        }
        LocalDateTime startTime = yesterdayDateTime.withHour(Integer.parseInt(nightShiftArr[0]))
            .withMinute(Integer.parseInt(nightShiftArr[1])).withSecond(0);
        LocalDateTime currDate = LocalDateTime.now();
        if(StringUtils.isNotBlank(date) && !date.equals(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))) {
            currDate = LocalDateTime.parse(date + " 23:59:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }
        LocalDateTime endTime = currDate.isBefore(currDate.withHour(Integer.parseInt(dayShiftArr[0])).withMinute(Integer.parseInt(dayShiftArr[1])))
            ?currDate:currDate.withHour(Integer.parseInt(dayShiftArr[0])).withMinute(Integer.parseInt(dayShiftArr[1]));

        List<SysProduceRecordStatisticsVo> sysProduceRecordStatisticsVos = baseMapper.selectDailyOut(startTime, endTime);
        Map<String, List<SysProduceRecordStatisticsVo>> map = sysProduceRecordStatisticsVos.stream()
                .collect(Collectors.groupingBy(SysProduceRecordStatisticsVo::getProductType));

        DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm");
        while (startTime.isBefore(endTime)) {
            hours.add(df.format(startTime));
            startTime = startTime.plusHours(1);
        }

        map.forEach((k, v) -> {
            List<Integer> list = new ArrayList<>();
            for (String hour : hours) {
                boolean flag = false;//标记当前该小时，在数据库是否有数据，如果有数据说明有物料，
                for (SysProduceRecordStatisticsVo vo : v) {
                    if (hour.contains(vo.getCurHour())) {
                        list.add(vo.getCount());
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    list.add(0);
                }
            }
            maps.put(k, list);
        });
        maps.put("hours", hours);
        return maps;
    }

    @Override
    public List<Map<String, Object>> getSystemData() {
        return baseMapper.getSystemData();
    }

}
